package com.itheima;

import java.io.*;
import java.net.Socket;
import java.util.*;

public class ChatServerThread extends Thread {
    private Socket socket;

    public ChatServerThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            // 1.从socket中去获取当前客户端的输入流
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            while (true) {
                // 读取客户端发送过来的消息
                String flag = br.readLine();

                // 对客户端的消息进行处理（请在此基础上进行功能完善！）
                switch (flag) {

                    case "100":// 100: 表示登陆
                        doLogin(br);
                        break;
                    case "101":
                        doRegister(br);
                        break;
                    case "200": // 200: 表示单聊
                        doSingleChat(br);
                        break;
                    case "201": // 201: 表示群聊
                        doAllChat(br);
                        break;
                    case "202": // 202: 随机聊
                        doRandomChat(br);
                        break;
                    case "300": // 300: 表示所有在线用户
                        dogetAllOnlineUser(br);
                        break;
                    case "301": // 301: 表示所有在线用户按用户名升序排序
                        dogetAllOnlineUserAscByUsername(br);
                        break;
                    case "302": // 302: 表示指定性别在线用户
                        dogetOnlineUserBySex(br);
                        break;
                }
            }
        } catch (Exception e) {
            //打印异常信息，方便调试bug，开发完成可以删除掉，达到优化效果
            e.printStackTrace();

            try {
                System.out.println("当前有人下线了！");
                // 从在线socket集合中移除本socket
                ChatServer.allSocketOnLine.remove(socket);
                // 发送在线用户给所有人
                String values = ChatServer.allSocketOnLine.values().toString();
                sendMsgToAllClient("有用户下线了，当前在线用户： " + values);
            } catch (Exception exception) {
                exception.printStackTrace();
            }
        }
    }

    /**
     * 用户登录
     * @param br
     * @throws Exception
     */
    private void doLogin(BufferedReader br) throws Exception {
        // 登录消息: 用户登录发送过来的数据格式为:用户名

        String userName = br.readLine();

        String ip = socket.getInetAddress().getHostAddress();

        //在已注册用户集合中查找是否有此用户
        List<User> registerUsers = ChatServer.registerUsers;
        for (User user : registerUsers) {
            if ((user.getUserName()).equals(userName)){
                //已注册用户中有此用户
                ChatServer.allSocketOnLine.put(socket, user);
                // 发送在线用户给所有人
                String values = userName + "用户登录了, 当前在线：" + ChatServer.allSocketOnLine.values().toString();
                sendMsgToAllClient(values);
                return;
            }
        }
        //用户不存在，登录失败
        PrintStream ps = new PrintStream(socket.getOutputStream());
        ps.println(userName+"用户未注册, 登陆失败!");
        ps.flush();

    }


    /**
     * 用户注册
     * @param br
     * @throws Exception
     */

    private void doRegister(BufferedReader br) throws Exception {

        List<User> registerUsers = ChatServer.registerUsers;
        //保存名字
        String Data = br.readLine();
        String[] split = Data.split(",");
        String name = split[0];
        //保存性别
        String sex = split[1];
        //保存年龄
        String ageStr = split[2];
        //把String类型的age换成int类型
        int age = Integer.parseInt(ageStr);

        PrintStream ps = new PrintStream(socket.getOutputStream());
        //遍历集合，看用户名是否存在
        for (User u : registerUsers) {
            if (u.getUserName().equals(name)) {
                ps.println(name + "用户已经存在，注册失败!");
                ps.close();
                return;
            }
        }
        //添加用户
        String ip = socket.getInetAddress().getHostAddress();
        User user = new User(name, sex, ip, age, false);
        //把注册的用户信息存在一个路径是模块里的chatserver文件夹的userData文件夹的Data.txt文件里面
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("chatserver\\userData\\Data.txt"));

        oos.writeObject(user);

        registerUsers.add(user);
        ps.println("你收到信息：恭喜您：" + name + "注册成功！");
        ps.flush();

        oos.writeObject(null);
        oos.close();
    }


    /**
     * 单聊
     * 一对一聊天
     * @param br
     * @throws Exception
     */
    private void doSingleChat(BufferedReader br) throws Exception {
        // 获取私发的目标客户
        String destName = br.readLine();
        // 获取私发消息
        String privateMsg = br.readLine();
        //私发给目标客户
        sendMsgToOneClient(destName, ChatServer.allSocketOnLine.get(socket).getUserName() + "对你说： " + privateMsg);
    }

    /**
     * 群聊
     * 管理员给所有人发信息
     * @param br
     * @throws Exception
     */
    private void doAllChat(BufferedReader br) throws Exception {
        // 群发消息
        String msg = br.readLine();
        // 群发消息给所有人
        if (ChatServer.allSocketOnLine.get(socket).isAdmin()){
            sendMsgToAllClient(ChatServer.allSocketOnLine.get(socket).getUserName() + "对所有人说： " + msg);
        } else {
            PrintStream ps = new PrintStream(socket.getOutputStream());
            ps.println("您不是管理员,不能群发消息!");
            ps.flush();
        }
    }

    /**
     * 随机聊
     * 发送一条信息给随机一个在线用户
     * @param br
     * @throws Exception
     */
    private void doRandomChat(BufferedReader br) throws Exception {

        //创建随机获取List<User>的索引
        Random r=new Random();
        int size = ChatServer.registerUsers.size();
        int usergetsize = r.nextInt(size);
        //根据从已有的注册用户中随机获取一个用户
        String randomName = ChatServer.registerUsers.get(usergetsize).getUserName();


        //获取随机发的消息
        String randomMsg = br.readLine();

        // 随机发给目标客户
        sendMsgToRandomClient(randomName,ChatServer.allSocketOnLine.get(socket).getUserName() + " 对你说: " +randomMsg);
    }


    /**
     * 获取在线用户根据用户名进行升序排序
     * @param br
     * @throws Exception
     */
    private void dogetAllOnlineUserAscByUsername(BufferedReader br) throws Exception {

        Collection<User> values = ChatServer.allSocketOnLine.values();
        TreeSet<User> treeSet = new TreeSet<>(new Comparator<User>() {
            @Override
            public int compare(User o1, User o2) {
                return o1.getUserName().compareTo(o2.getUserName());
            }
        });
        for (User user : values) {
            treeSet.add(user);
        }
        String s = treeSet.toString();
        int size = treeSet.size();
        String count = "当前在线人数："+size;
        PrintStream ps = new PrintStream(socket.getOutputStream());
        ps.println(count);
        ps.println("根据用户名升序排序的用户:"+s);
        ps.flush();


    }

    //获取指定性别在线用户
    private void dogetOnlineUserBySex(BufferedReader br) throws Exception {
        String sex = br.readLine();
        List<User> onlineUser = new ArrayList<>();
        Collection<User> users = ChatServer.allSocketOnLine.values();
        for (User user : users) {
            if (user.getSex().equals(sex)){
                onlineUser.add(user);
            }
        }

        PrintStream ps = new PrintStream(socket.getOutputStream());
        ps.println("当前在线的"+sex+"性用户人数为："+onlineUser.size());
        ps.println("当前在线的"+sex+"性用户："+onlineUser.toString());
        ps.flush();

    }

    //获取所有在线用户
    private void dogetAllOnlineUser(BufferedReader br) throws Exception {

        String onlineUser = ChatServer.allSocketOnLine.values().toString();
        PrintStream ps = new PrintStream(socket.getOutputStream());
        ps.println("当前在线人数为："+ChatServer.allSocketOnLine.values().size());
        ps.println("当前在线用户："+onlineUser);
        ps.flush();

    }




    /**
     * 把消息发给一个指定的客户端
     *
     * @param destName 目标用户名
     * @param privateMsg 要发送的消息
     * @throws Exception
     */
    private void sendMsgToOneClient(String destName, String privateMsg) throws Exception {
        //根据用户名从所有在线用户找到目标用户，私发消息
        Set<Socket> keySet = ChatServer.allSocketOnLine.keySet();
        for (Socket sk : keySet) {
            User user = ChatServer.allSocketOnLine.get(sk);
            if (user.getUserName().equals(destName)) {
                PrintStream ps = new PrintStream(sk.getOutputStream());
                ps.println(privateMsg);
                ps.flush();
                break;
            }
        }
    }

    /**
     * 把当前客户端发来的消息推送给全部在线的socket
     *
     * @param msg 要群发的消息
     */
    private void sendMsgToAllClient(String msg) throws Exception {
        Set<Socket> keySet = ChatServer.allSocketOnLine.keySet();
        for (Socket sk : keySet) {
            PrintStream ps = new PrintStream(sk.getOutputStream());
            ps.println(msg);
            ps.flush();
        }
    }


    /**
     * 把当前客户端发来的消息随机推送给一个在线的socket
     * @param randomName
     * @param randomMsg
     * @throws Exception
     */
    private void sendMsgToRandomClient(String randomName, String randomMsg) throws Exception {
        //根据用户名从所有在线用户找到随机用户，随机发消息
        Set<Socket> keySet = ChatServer.allSocketOnLine.keySet();
        for (Socket sk : keySet) {
            User user = ChatServer.allSocketOnLine.get(sk);
            if (user.getUserName().equals(randomName)) {
                PrintStream ps = new PrintStream(sk.getOutputStream());
                ps.println(randomMsg);
                ps.flush();
                break;
            }
        }
    }
}

